#include <glib.h>

typedef struct employee_info_tag {
    gint id;
    gchar *name;
}employee_info_t;

static void _list_struct_print_func(gpointer data, gpointer user_data)
{
    employee_info_t *einfo = NULL;

    einfo = (employee_info_t *)data;
    if(NULL == einfo) {
        g_print("input param error! \n");
        return;
    }

    g_print("user_data:%s, einfo->id:%d, einfo->name:%s \n", (gchar *)user_data, einfo->id, einfo->name);
}

static void _list_struct_free_func(gpointer data)
{
    employee_info_t *einfo = NULL;

    einfo = (employee_info_t *)data;

    if( (NULL != einfo) && (NULL != einfo->name) ) {
        g_free(einfo->name);
    }

    if(NULL != einfo) {
        g_free(einfo);
    }
}

static gint _list_struct_name_cmp_func(gconstpointer a, gconstpointer b)
{
    employee_info_t *einfo_a = NULL;
    employee_info_t *einfo_b = NULL;

    einfo_a = (employee_info_t *)a;
    einfo_b = (employee_info_t *)b;

    if( (NULL == einfo_a) || (NULL == einfo_b) ) {
        g_print("input param error! \n");
        return 0;
    }

    return g_strcmp0(einfo_a->name, einfo_b->name);
}

static gint _list_struct_id_cmp_func(gconstpointer a, gconstpointer b)
{
    employee_info_t *einfo_a = NULL;
    employee_info_t *einfo_b = NULL;

    einfo_a = (employee_info_t *)a;
    einfo_b = (employee_info_t *)b;

    if( (NULL == einfo_a) || (NULL == einfo_b) ) {
        g_print("input param error! \n");
        return 0;
    }

    return (einfo_a->id - einfo_b->id);
}

static gint _list_struct_id_find_func(gconstpointer a, gconstpointer b)
{
    employee_info_t *einfo_a = NULL;
    gint id;

    einfo_a = (employee_info_t *)a;
    id = GPOINTER_TO_INT(b);

    if (NULL == einfo_a) {
        g_print("input param error! \n");
        return 0;
    }

    return (einfo_a->id - id);
}

static gint _list_struct_name_find_func(gconstpointer a, gconstpointer b)
{
    employee_info_t *einfo_a = NULL;
    gchar *name = NULL;

    einfo_a = (employee_info_t *)a;
    name = (gchar *)b;

    if (NULL == einfo_a) {
        g_print("input param error! \n");
        return 0;
    }

    return g_strcmp0(einfo_a->name, name);
}

static gpointer _list_struct_copy_func(gconstpointer src, gpointer data)
{
    employee_info_t *einfo = NULL;

    einfo = g_new0(employee_info_t, 1);

    einfo->id = ((employee_info_t *)src)->id + GPOINTER_TO_INT(data);
    einfo->name = g_strdup(((employee_info_t *)src)->name);

    return (gpointer)einfo;
}

gint main(gint argc, gchar **argv)
{
    GList *list = NULL;
    GList *l = NULL;
    GList *list2 = NULL;

    employee_info_t *einfo[4] = {NULL, NULL, NULL, NULL};

    einfo[0] = g_new0(employee_info_t, 1);
    einfo[1] = g_new0(employee_info_t, 1);
    einfo[2] = g_new0(employee_info_t, 1);
    einfo[3] = g_new0(employee_info_t, 1);

    einfo[0]->id = 1000;
    einfo[0]->name = g_strdup("Jack");
    einfo[1]->id = 1001;
    einfo[1]->name = g_strdup("Pony");
    einfo[2]->id = 1002;
    einfo[2]->name = g_strdup("Robin");
    einfo[3]->id = 1003;
    einfo[3]->name = g_strdup("NoName");

    list = g_list_append(list, (gpointer)einfo[0]); //Jack
    list = g_list_prepend(list, (gpointer)einfo[1]); //Pony->Jack
    list = g_list_insert(list, (gpointer)einfo[2], 1); //Pony->Robin->Jack

    l = g_list_nth(list, 0);
    list = g_list_insert_before(list, l, (gpointer)einfo[3]); //NoName->Pony->Robin->Jack

    g_list_foreach(list, _list_struct_print_func, "ori");

    // #sort
    list = g_list_sort(list, _list_struct_id_cmp_func);

    g_list_foreach(list, _list_struct_print_func, "id sort");

    list = g_list_sort(list, _list_struct_name_cmp_func);

    g_list_foreach(list, _list_struct_print_func, "name sort");

    // #find
    l = g_list_find_custom(list, GINT_TO_POINTER(1002), _list_struct_id_find_func);
    if( NULL != l) {
        g_print("found by id! id=%d, name=%s \n", ((employee_info_t *)l->data)->id, ((employee_info_t *)l->data)->name);
    } else {
        g_print("can not found by id! \n");
    }

    l = g_list_find_custom(list, (gpointer)"Jack", _list_struct_name_find_func);
    if( NULL != l) {
        g_print("found by name! id=%d, name=%s \n", ((employee_info_t *)l->data)->id, ((employee_info_t *)l->data)->name);
    } else {
        g_print("cat not found by name! \n");
    }

    // #copy
    list2 = g_list_copy_deep(list, _list_struct_copy_func, GINT_TO_POINTER(5000));

    g_list_foreach(list2, _list_struct_print_func, "list2");
    g_list_free_full(list2, _list_struct_free_func);

    g_list_free_full(list, _list_struct_free_func);

    return 0;
}